package afcp.alumni.dao.base;

import java.io.Serializable;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

import net.sf.jsr107cache.Cache;
import net.sf.jsr107cache.CacheException;
import net.sf.jsr107cache.CacheFactory;
import net.sf.jsr107cache.CacheManager;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.stereotype.Component;

import afcp.alumni.model.base.DatastoreEntity;

@Component
public class DaoCacheImpl implements DaoCache {
	
	private static final Log logger = LogFactory.getLog(DaoCacheImpl.class);

	private Cache newCache() {
		try {
			CacheFactory cacheFactory = CacheManager.getInstance()
					.getCacheFactory();
			Cache cache = cacheFactory.createCache(Collections.emptyMap());
			return cache;
		} catch (CacheException e) {
			logger.error("Could  not get cache.", e);
			return null;
		}
	}
	
	private Cache cache = null;
	private synchronized Cache getCache() {
		if (cache == null) {
			cache = newCache();
		}
		return cache;
//		return newCache();
	}
	
	// basic methods
	
	@Override
	public void put(Serializable key, Serializable value) {
		getCache().put(key, value);
	}

	@Override
	public void putAll(Map<Serializable, Serializable> t) {
		getCache().putAll(t);
	}

	@Override
	public Object get(String id, String entityName) {
		return getCache().get(entityName + "." + id);
	}

	@Override
	public <T extends Object> Map<T, Serializable> get(Collection<T> keys,
			String entityName) {
		try {
			@SuppressWarnings("unchecked")
			Map<T, Serializable> result = getCache().getAll(keys);
			return result;
		} catch (CacheException e) {
			logger.error("An error has occurred while getting the cache with keys: " + keys, e);
			return null;
		}
	}

	@Override
	public Object remove(String id, String entityName) {
		return getCache().remove(entityName + "." + id);
	}

	@Override
	public boolean containsKey(Serializable key) {
		return getCache().containsKey(key);
	}

	@Override
	public boolean isEmpty() {
		return getCache().isEmpty();
	}

	@Override
	public int size() {
		return getCache().size();
	}
	
	// end basic methods
	
	
	// specific methods

	@Override
	public <T extends DatastoreEntity> void putEntitiesById(Collection<T> entities,
			String entityName) {
		Map<String, T> cachedEntities = new HashMap<String, T>(entities.size());
		for (T entity : entities) {
			cachedEntities.put(entityName + "." + entity.getId(), entity);
		}
		Cache cache = getCache();
		cache.putAll(cachedEntities);
	}

}
